/*
 * Teste
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package tp_sd_cliente.model;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
import java.util.List;
import javax.swing.SwingWorker;
import tp_sd_base.ClientSocketChat;
import tp_sd_base.IClient;
import tp_sd_base.IServer;
import tp_sd_base.IServer.ERROR_TYPE;
import tp_sd_base.Set;
import tp_sd_cliente.gui.ClientGUI;

/**
 *
 * @author kill9
 */
public class ClientChat implements IClient{

    public interface IClientListener{
        
        public void onError(ERROR_TYPE eRROR_TYPE, String errorType);

        public void onLogin(String readUTF);

        public void onLogOut();
        
        public void onMessage(String nickName, String readUTF);

        public void onRanking(int readInt, List<Set<String,Integer>> list);

        public void onRefresh(int readInt, List<String> list);

        public void onPartialRefresh(int readInt,int  operation ,List<String> list);

        public void onInvalidOperation(int value);

        public void onInvalidArgs();
    }

    private ClientSocketChat clientSocketChat;

    private IClientListener listener;

    public ClientChat() {
    
    }

    public void setListener(IClientListener listener) {
        this.listener = listener;
    }

    public void login(byte [] ip,int port,String nickName,String password,boolean registration) throws IOException{
        try{
        if(clientSocketChat==null || clientSocketChat.isClosed()){
            Socket socket = new Socket(InetAddress.getByAddress(ip),port);
            clientSocketChat = new ClientSocketChat(socket, this);

            SwingWorker swingWorker = new SwingWorker() {

                @Override
                protected Object doInBackground() throws Exception {
                        while(clientSocketChat!=null && !clientSocketChat.isClosed()){
                            clientSocketChat.readMessage();
                        }
                    return null;
                    }

                };
                swingWorker.execute();

            ObjectOutputStream outputStream = clientSocketChat.getOutputStream();

            outputStream.writeInt(registration?IServer.MESSAGE_TYPE.REGISTRATION.ordinal():IServer.MESSAGE_TYPE.LOGIN.ordinal());
            outputStream.writeUTF(nickName);
            outputStream.writeUTF(password);
            outputStream.flush();                
        }
        }catch(SocketException exception){
            this.disconnect();
            //throw exception;
        }catch(IOException ioe ){
            this.disconnect();
            //throw ioe;
        }
    }

    public boolean isClosed(){
        return clientSocketChat== null || clientSocketChat.isClosed();
    }

    public void onError(ERROR_TYPE eRROR_TYPE, String errorType) {
        if(eRROR_TYPE.equals(IServer.ERROR_TYPE.LOGIN) || eRROR_TYPE.equals(IServer.ERROR_TYPE.REGISTRATION)){
            try {
                clientSocketChat.close();
                clientSocketChat = null;
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        if(listener!=null){
            listener.onError(eRROR_TYPE, errorType);
        }
    }


    public String nick;

    public void onLogin(String readUTF) {
        nick = readUTF;
        if(listener!=null){
            listener.onLogin(readUTF);
        }
    }

    public void onLogOut() {
        if(listener!=null){
            listener.onLogOut();
        }
    }

    public void onMessage(String nickName, String readUTF) {
        if(listener!=null){
            listener.onMessage(nickName, readUTF);
        }
    }

    public void onRanking(int readInt, List<Set<String,Integer>> list) {
        if(listener!=null){
            listener.onRanking(readInt, list);
        }
    }

    public void onRefresh(int readInt, List<String> list) {
        if(listener!=null){
            listener.onRefresh(readInt, list);
        }
    }

    public void onInvalidOperation(int value) {
        if(listener!=null){
            listener.onInvalidOperation(value);
        }
    }

    public void onPartialRefresh(int readInt, int operation,List<String> string) {
        if(listener!=null){
            listener.onPartialRefresh(readInt, operation,string);
        }
    }

    public void onInvalidArgs() {
        if(listener!=null){
            listener.onInvalidArgs();
        }
    }

    public void sendMessage(String string) throws IOException{
        this.clientSocketChat.sendMessage(IServer.MESSAGE_TYPE.MESSAGE, string);
    }

    public void disconnect() throws IOException{
        clientSocketChat.close();
    }

    public void sendAddUsers(List<String> list) throws IOException{
        clientSocketChat.sendMessage(IServer.MESSAGE_TYPE.INSERT.ordinal(), null, null, null,list);
    }

    public void sendRemoveUsers(List<String> list) throws IOException{
        clientSocketChat.sendMessage(IServer.MESSAGE_TYPE.DELETE.ordinal(), null, null, null,list);
    }

    public void refresh() throws IOException{
        clientSocketChat.initValues();
    }

    public void topUserMessages() throws IOException{
        clientSocketChat.sendMessage(IServer.MESSAGE_TYPE.RANKING.ordinal(), IServer.RANKING.MESSAGES.ordinal(), 10,null,null);
    }

    public void topUserFollowers() throws IOException{
        clientSocketChat.sendMessage(IServer.MESSAGE_TYPE.RANKING.ordinal(), IServer.RANKING.FOLLOWERS.ordinal(), 10,null,null);
    }
}
